#include "uti_ordersysmapseries.h"
#include "uti_consolecolor.h"
#pragma warning(disable : 4996)



//OrderSysMapSeries::OrderSysMapSeries(OrderSysMapSerInfo* pserinfo)
//{
//	memcpy(&m_mapserinfo, pserinfo, sizeof(OrderSysMapSerInfo));
//
//	m_pmemman = new MemMan<OrderSysMap>(m_mapserinfo.sersize, m_mapserinfo.p);
//
//	m_pmemman->InitUnitPointer(&m_pmapcur, &m_mapindex);
//
//}

OrderSysMapSeries::OrderSysMapSeries(unsigned int sersize, void (*p)())
{
	m_mapserinfo.sersize = sersize;
	m_mapserinfo.p = p;

	m_pmemman = new MemMan<OrderSysMap>(m_mapserinfo.sersize, m_mapserinfo.p);

	m_pmemman->InitUnitPointer(&m_pmapcur, &m_mapindex);

	m_psercommision = NULL;
}


OrderSysMapSeries::~OrderSysMapSeries()
{
	if (NULL != m_pmemman)
	{
		delete m_pmemman;
	}

	if (m_psercommision)
	{
		delete m_psercommision;
	}
}

//
//void OrderSysMapSeries::Addorder(TThostFtdcInstrumentIDType* pinst, TThostFtdcOrderRefType* porderref, TThostFtdcVolumeType reqvol)
//{
//	///////This is not work logic but memory management logic ///////////
//	if (m_pmapcur->changecnt != 0) 
//	{
//		m_pmemman->NextUnitPointer(&m_pmapcur,&m_mapindex);//get cur bar pointer and index
//
//	}
//
//	strcpy(m_pmapcur->inst, *pinst);
//
//	strcpy(m_pmapcur->orderref, *porderref);
//
//	m_pmapcur->reqvol = reqvol;
//
//	m_pmapcur->leftvol = reqvol;
//
//	m_pmapcur->changecnt++;
//}


void OrderSysMapSeries::Addorder(TThostFtdcInstrumentIDType* pinst, TThostFtdcOrderRefType* porderref, TThostFtdcVolumeType reqvol, TThostFtdcDirectionType direct,
	char offset)
{
	///////This is not work logic but memory management logic ///////////
	if (m_pmapcur->changecnt != 0) 
	{
		m_pmemman->NextUnitPointer(&m_pmapcur,&m_mapindex);//get cur bar pointer and index

	}

	strcpy(m_pmapcur->inst, *pinst);

	strcpy(m_pmapcur->orderref, *porderref);

	m_pmapcur->reqvol = reqvol;

	m_pmapcur->leftvol = reqvol;

	m_pmapcur->direct = direct;

	m_pmapcur->offset = offset;

	m_pmapcur->changecnt++;
}

//void OrderSysMapSeries::Newmaporder(TThostFtdcOrderRefType* porderref, TThostFtdcVolumeType reqvol)
//{
//
//}

bool OrderSysMapSeries::FindorderAndSet(CThostFtdcOrderField* porder)//used in order judgement
{
	bool bfound = false;
	unsigned int index = 0;
	OrderSysMap* pb4map = NULL;


	//printf("[FindorderAndSet] Dest Orderref is: ", porder->OrderRef);

	for(index = 0; index <= m_mapindex; index++)
	{
		pb4map = m_pmapcur - index;

		//printf("[FindorderAndSet] mapser index is:%d, Dest Orderrefis: %s, mapser Orderref is: %s", index, porder->OrderRef, pb4map->order);

		if (0 == strcmp(pb4map->orderref, porder->OrderRef))
		{
			strcpy(pb4map->sysid, porder->OrderSysID);
			strcpy(pb4map->exchangeid, porder->ExchangeID);
			//strcpy(pb4map->inst, porder->InstrumentID);
			pb4map->orderstatus = porder->OrderStatus;


			pb4map->changecnt++;
			bfound = true;
			break;
		}
	}

	return bfound;
}




bool OrderSysMapSeries::Findorder_exch_sys_setvol(CThostFtdcTradeField* ptrade)//used in order judgement
{
	bool bfound = false;
	unsigned int index = 0;
	OrderSysMap* pb4map = NULL;

	for(index = 0; index <= m_mapindex; index++)
	{
		pb4map = m_pmapcur - index;
		if (0 == strcmp(pb4map->orderref, ptrade->OrderRef))
		{
			if (0 == strcmp(pb4map->sysid, ptrade->OrderSysID) && (0 == strcmp(pb4map->exchangeid, ptrade->ExchangeID)))
			{
				pb4map->tradevol += ptrade->Volume;

				pb4map->leftvol -= ptrade->Volume;

				pb4map->tradeamount += ptrade->Price * ptrade->Volume;

				bfound = true;
				break;
			}
		}
	}


	return bfound;
}




bool OrderSysMapSeries::Addreqcanvol(TThostFtdcOrderRefType* orderref, TThostFtdcExchangeIDType* exchangeId, TThostFtdcOrderSysIDType* ordersysId)
{
	bool bfound = false;
	unsigned int index = 0;
	OrderSysMap* pb4map = NULL;

	for(index = 0; index <= m_mapindex; index++)
	{
		pb4map = m_pmapcur - index;
		if (0 == strcmp(pb4map->orderref, *orderref))
		{
			//if (0 == strcmp(pb4map->sysid, *ordersysId) && (0 == strcmp(pb4map->exchangeid, *exchangeId)))
			{
				pb4map->reqcanvol = pb4map->leftvol;

				bfound = true;
				break;
			}
		}
	}


	return bfound;
}


bool OrderSysMapSeries::Findcancelorderforsucc(CThostFtdcOrderField* porder)
{
	bool bfound = false;
	unsigned int index = 0;
	OrderSysMap* pb4map = NULL;


	//printf("[FindorderAndSet] Dest Orderref is: ", porder->OrderRef);

	for(index = 0; index <= m_mapindex; index++)
	{
		pb4map = m_pmapcur - index;

		//printf("[FindorderAndSet] mapser index is:%d, Dest Orderrefis: %s, mapser Orderref is: %s", index, porder->OrderRef, pb4map->order);

		if (0 == strcmp(pb4map->orderref, porder->OrderRef))
		{
			//if (0 == strcmp(pb4map->sysid, porder->OrderSysID) && (0 == strcmp(pb4map->exchangeid, porder->ExchangeID)))
			{
				pb4map->orderstatus = porder->OrderStatus;

				pb4map->canvol = pb4map->reqcanvol;

				pb4map->reqcanvol = 0;
				//pb4map->reqvol -= pb4map->canvol; 

				pb4map->leftvol = 0;

				pb4map->changecnt++;
				bfound = true;
				break;
			}

		}
	}

	return bfound;
}


bool OrderSysMapSeries::Findcancelorderforfailed(CThostFtdcInputOrderActionField* pinputorderaction)
{

	bool bfound = false;
	unsigned int index = 0;
	OrderSysMap* pb4map = NULL;


	//printf("[FindorderAndSet] Dest Orderref is: ", porder->OrderRef);

	for(index = 0; index <= m_mapindex; index++)
	{
		pb4map = m_pmapcur - index;

		//printf("[FindorderAndSet] mapser index is:%d, Dest Orderrefis: %s, mapser Orderref is: %s", index, porder->OrderRef, pb4map->order);

		if (0 == strcmp(pb4map->orderref, pinputorderaction->OrderRef))
		{
			//if (0 == strcmp(pb4map->sysid, pinputorderaction->OrderSysID) && (0 == strcmp(pb4map->exchangeid, pinputorderaction->ExchangeID)))
			{
				//pb4map->orderstatus = porder->OrderStatus;

				pb4map->reqcanvol = 0;





				//if (pb4map->leftvol == 0)
				//{

				//}
				//else
				//{
				//	SetConsoleColor(FOREGROUND_GREEN);  
				//	cerr << "[Findcancelorderforfailed] Orderref: "<<pb4map->orderref<<" leftvol is NOT zero"<<endl;
				//	SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);  
				//}

				pb4map->changecnt++;
				bfound = true;
				break;
			}

		}
	}

	return bfound;


}




bool OrderSysMapSeries::Getmap(TThostFtdcOrderRefType* porder, OrderSysMap* &poutmap)
{
	bool bfound = false;
	unsigned int index = 0;
	OrderSysMap* pb4map = NULL;

	for(index = 0; index <= m_mapindex; index++)
	{
		pb4map = m_pmapcur - index;

		if (0 == strcmp(pb4map->orderref, *porder))
		{
			poutmap = pb4map;
			bfound = true;
			break;
		}
	}

	return bfound;

}



bool OrderSysMapSeries::Getmap_New(TThostFtdcOrderRefType orderref, OrderSysMap* &poutmap)
{
	bool bfound = false;
	unsigned int index = 0;
	OrderSysMap* pb4map = NULL;

	for(index = 0; index <= m_mapindex; index++)
	{
		pb4map = m_pmapcur - index;

		if (0 == strcmp(pb4map->orderref, orderref))
		{
			poutmap = pb4map;
			bfound = true;
			break;
		}
	}

	return bfound;

}


bool OrderSysMapSeries::Setcommisionrate(CThostFtdcInstrumentCommissionRateField* pfield)
{
	m_psercommision = pfield;

	return true;
}


bool OrderSysMapSeries::GetOrdermapserProfit(OrderMapSerProfit& profit)
{
	if (0 == m_mapindex && 0 == m_pmapcur->changecnt )
	{
		return false;
	}



	for (unsigned int index = 0; index <= m_mapindex; index++)
	{
		OrderSysMap* pordermap = m_pmapcur - (m_mapindex - index);

		if (pordermap->direct == THOST_FTDC_D_Buy && pordermap->offset == THOST_FTDC_OF_Open)
		{
			profit.buyopen_amount += pordermap->tradeamount;
			profit.buyopen_vol += pordermap->tradevol;
		}
		else if (pordermap->direct == THOST_FTDC_D_Buy && pordermap->offset == THOST_FTDC_OF_CloseToday)
		{
			profit.buyclose_amount += pordermap->tradeamount;
			profit.buyclose_vol += pordermap->tradevol;
		}
		else if (pordermap->direct == THOST_FTDC_D_Sell && pordermap->offset == THOST_FTDC_OF_Open)
		{
			profit.sellopen_amount += pordermap->tradeamount;
			profit.sellopen_vol += pordermap->tradevol;
		}		
		else if (pordermap->direct == THOST_FTDC_D_Sell && pordermap->offset == THOST_FTDC_OF_CloseToday)
		{
			profit.sellclose_amount += pordermap->tradeamount;
			profit.sellclose_vol += pordermap->tradevol;
		}
			

		

	}

	//buy profit 
	profit.buy_profit = profit.buyclose_amount - profit.buyopen_amount;

	//sell profit 
	profit.sell_profit = profit.sellopen_amount - profit.sellclose_amount;


	//buy/sell Open Commision
	if (m_psercommision->OpenRatioByMoney != 0)
	{
		profit.buyopen_commision = profit.buyopen_amount * m_psercommision->OpenRatioByMoney;
		profit.sellopen_commision = profit.sellopen_amount * m_psercommision->OpenRatioByMoney;
	}	
	else if (m_psercommision->OpenRatioByVolume != 0)
	{
		profit.buyopen_commision = profit.buyopen_vol * m_psercommision->OpenRatioByVolume;
		profit.sellopen_commision = profit.sellopen_vol * m_psercommision->OpenRatioByVolume;
	}
		

	//buy/sell CloseToday Commision
	if (m_psercommision->CloseTodayRatioByMoney != 0)
	{
		profit.buyclose_commision = profit.buyclose_amount * m_psercommision->OpenRatioByMoney;
		profit.sellclose_commision = profit.sellclose_amount * m_psercommision->OpenRatioByMoney;
	}	
	else if (m_psercommision->CloseTodayRatioByVolume != 0)
	{
		profit.buyclose_commision = profit.buyclose_vol * m_psercommision->OpenRatioByVolume;
		profit.sellclose_commision = profit.sellclose_vol * m_psercommision->OpenRatioByVolume;
	}

	
	profit.totalprofit = profit.buy_profit + profit.sell_profit - profit.buyopen_commision - profit.buyopen_commision - profit.sellopen_commision - profit.sellclose_commision;

	return true;
}